package com.sm.healthy.ui.fragment

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothGatt
import android.content.Context
import android.content.Intent
import android.location.LocationManager
import android.os.Bundle
import android.provider.Settings
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.blackflagbin.kcommon.utils.PermissionUtils
import com.clj.fastble.callback.BleGattCallback
import com.clj.fastble.callback.BleNotifyCallback
import com.clj.fastble.callback.BleScanCallback
import com.clj.fastble.data.BleDevice
import com.clj.fastble.exception.BleException
import com.clj.fastble.utils.HexUtil
import com.lishuaihua.toast.ToastUtils
import com.sm.healthy.R
import com.sm.healthy.base.BaseFragment
import com.sm.healthy.base.handle.TopHandle
import com.sm.healthy.data.bean.TemperatureEntity
import com.sm.healthy.databinding.FragmentTemperatureMBinding
import com.sm.healthy.model.TemperatureModel
import com.sm.healthy.ui.dialog.BloodOxygenDialog3
import com.sm.healthy.utils.BleUtils
import me.hgj.jetpackmvvm.ext.nav
import java.lang.ref.WeakReference

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [TemperatureMFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class TemperatureMFragment :
    BaseFragment<TemperatureModel, FragmentTemperatureMBinding>() {

    companion object {
        //*******************************************************蓝牙数据交互 命令字*********************************************
        const val DEVICES_TEMP_FLAG = "FF080431";
        const val SYS_BLUETOOTH_NAME = "FeverCat"
    }

    private val bleUtils by lazy {
        BleUtils(SYS_BLUETOOTH_NAME)
    }

    private var bloodOxygenDialog3: BloodOxygenDialog3? = null

    override fun layoutId(): Int {
        return R.layout.fragment_temperature_m
    }

    override fun initView(savedInstanceState: Bundle?) {
        mDatabind.handle = TopHandle(nav())
        mDatabind.model = mViewModel

        mDatabind.tvBtnStart.setOnClickListener {
            startMeasure()
        }
    }

    private fun startMeasure() {
        if (!bleUtils.checkBle()) return
        if (!mViewModel.isStart.get())
            PermissionUtils.location(requireActivity(), {
                startScan()
            })
        else {
            stop()
        }
    }

    private fun stop() {

        mViewModel.isStart.set(false)
        mDatabind.tvBtnStart.text = "开始测量"
        mDatabind.tvBtnStart.setBackgroundResource(R.drawable.bg_btn_blue_shape)
        bleUtils.disconnect()
        saveData()
    }

    private fun startScan() {
        when {
            bleUtils.bleIsOpen().not() -> openBle()
            checkGPSIsOpen().not() -> openGPS()
            else -> scan()
        }
    }

    private fun finishScan(result: BleDevice) {
        bleUtils.connect(result, MyBleGattCallback(this))
    }

    private fun scan() {
        bleUtils.startScan(MyBleScanCallback(this))
    }

    private fun connectSuccess() {
        mViewModel.isStart.set(true)
        mDatabind.tvBtnStart.text = "停止测量"
        mDatabind.tvBtnStart.setBackgroundResource(R.drawable.bg_btn_red_shape)
        bleUtils.notifyCharacteristic(object : BleNotifyCallback() {
            override fun onNotifySuccess() {
            }

            override fun onNotifyFailure(exception: BleException?) {
            }

            override fun onCharacteristicChanged(data: ByteArray?) {
                onNotifyData(data ?: return)
            }

        })

    }

    private fun onNotifyData(bytes: ByteArray) {
        val head = bytes[0].toInt().and(0xff)
        val type = bytes[1].toInt().and(0xff)
        if (head == 0xff && type == 0x08) {
            val tempData = subTempConvert10(HexUtil.encodeHexStr(bytes))
            val subHexInt = tempData!![0]
            val subHexDecimal = tempData[1]
            val tempStr = subHexInt + subHexDecimal
            val dTempLeft = tempStr.toFloat()
            val tempLevel = when {
                dTempLeft <= 36.0 -> 1
                dTempLeft > 36.0 && dTempLeft < 38.0 -> 0
                else -> 2
            }
            mViewModel.tempStr.set(tempStr)
            mViewModel.insert(
                TemperatureEntity(
                    System.currentTimeMillis(),
                    temperature = dTempLeft,
                    levelTemperature = tempLevel
                )
            )
            mDatabind.tvLevel.changeLevel(level = tempLevel)
            stop()
        }

    }

    /**
     * 截取温度头部 并转换为十进制
     * 硬件已转为10进制 无需再转
     */
    fun subTempConvert10(flag: String): List<String>? {
        val tempData: MutableList<String> = ArrayList()
        if (DEVICES_TEMP_FLAG.length + 2 < flag.length && DEVICES_TEMP_FLAG.length + 4 < flag.length && DEVICES_TEMP_FLAG.length + 10 < flag.length) {
            // 整数位
            val subHexInt = flag.substring(
                DEVICES_TEMP_FLAG.length + 2,
                DEVICES_TEMP_FLAG.length + 4
            )
            // 小数位
            val subHexDecimal = flag.substring(
                DEVICES_TEMP_FLAG.length + 4,
                DEVICES_TEMP_FLAG.length + 6
            )
            val subHexInt2 = flag.substring(
                DEVICES_TEMP_FLAG.length + 6,
                DEVICES_TEMP_FLAG.length + 8
            )
            val subHexDecimal2 = flag.substring(
                DEVICES_TEMP_FLAG.length + 8,
                DEVICES_TEMP_FLAG.length + 10
            )
            //            String subHexDecimalStr = String.valueOf(getValue16To10(subHexDecimal));
            var subHexDecimalStr = subHexDecimal
            if (subHexDecimalStr.length >= 2) {
                subHexDecimalStr = subHexDecimalStr.substring(0, 2)
            } else {
                subHexDecimalStr += "0"
            }
            //            tempData.add(String.valueOf(getValue16To10(subHexInt)));
            tempData.add(subHexInt)
            tempData.add(".$subHexDecimalStr")
            tempData.add(subHexInt2)
            tempData.add(".$subHexDecimal2")

            //            DecimalFormat df = new DecimalFormat("#.00");
            //            Double dTemp = Double.valueOf(String.valueOf(getValue16To10(subHexInt)) + "." + String.valueOf(getValue16To10(subHexDecimal)));
            //            String format = df.format(dTemp);
            //
            //            LogUtils.logd("-- 温度整数:" + subHexInt + "," + getValue16To10(subHexInt));
            //            LogUtils.logd("-- 温度小数:" + format + "," + getValue16To10(subHexDecimal));
            return tempData
        }

        // 默认数据
        tempData.add("00")
        tempData.add(".00")
        return tempData
    }

    private fun saveData() {
//        if (recoderData2.size < 3) mViewModel.toast.postValue("数据过少，保存失败！")
//        else dealData()
//        clearDataRestart()
    }

    override fun onStop() {
        super.onStop()
        bleUtils.cancelScan()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        bleUtils.disconnect()
    }

    private fun checkGPSIsOpen(): Boolean {
        val locationManager =
            activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
    }

    private fun openBle() {
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        startActivityForResult(enableBtIntent, FetalHeartMFragment.REQUEST_ENABLE_BT)
    }

    private fun openGPS() {
        AlertDialog.Builder(requireActivity()).setMessage("开启GPS定位").setNegativeButton("取消", null)
            .setPositiveButton("打开") { _, _ ->
                val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                startActivityForResult(intent, FetalHeartMFragment.REQUEST_CODE_OPEN_GPS)
            }.show()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            FetalHeartMFragment.REQUEST_ENABLE_BT -> if (checkGPSIsOpen()) {
                scan()
            } else {
                openGPS()
            }
            FetalHeartMFragment.REQUEST_CODE_OPEN_GPS -> if (bleUtils.bleIsOpen()) {
                scan()
            } else {
                openBle()
            }
        }
    }

    class MyBleScanCallback(fragment: TemperatureMFragment) : BleScanCallback() {
        private val myFragment: WeakReference<TemperatureMFragment> = WeakReference(fragment)

        override fun onScanStarted(success: Boolean) {
            myFragment.get()?.showLoading("蓝牙扫描中")
        }

        override fun onScanning(result: BleDevice) {
            myFragment.get()?.finishScan(result)
        }

        override fun onScanFinished(scanResultList: List<BleDevice>) {
            myFragment.get()?.dismissLoading()
            if (scanResultList.isEmpty()) {
                ToastUtils.show("扫描失败")
            }
        }
    }

    class MyBleGattCallback(fragment: TemperatureMFragment) : BleGattCallback() {
        private val myFragment: WeakReference<TemperatureMFragment> = WeakReference(fragment)

        override fun onStartConnect() {
            myFragment.get()?.showLoading("蓝牙连接中")
        }

        override fun onConnectFail(bleDevice: BleDevice?, exception: BleException?) {
            myFragment.get()?.dismissLoading()
        }

        override fun onConnectSuccess(
            bleDevice: BleDevice?,
            gatt: BluetoothGatt?,
            status: Int
        ) {
            myFragment.get()?.dismissLoading()
            val services = gatt?.services
            myFragment.get()?.bleUtils?.getService(services, "6e400001")
            myFragment.get()?.connectSuccess()
            /*myFragment.get()
                ?.writeDataToBle(if (Config.isSingleEcg) GET_ECG2_WAVEFORM_ON else GET_ECG12_WAVEFORM_ON)*/
        }

        override fun onDisConnected(
            isActiveDisConnected: Boolean,
            device: BleDevice?,
            gatt: BluetoothGatt?,
            status: Int
        ) {
            myFragment.get()?.dismissLoading()
        }

    }
}